#
# This file is part of uscp, an open-source cross-platform package tool
# 2008  Rafael Sachetto
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Contact e-mail: Rafael Sachetto <rsachetto@gmail.com>
# Program URL   : http://code.google.com/p/uspc/

from PyQt4.QtCore import QThread, SIGNAL, QMutex, QString, \
     QDir, QFile, QWaitCondition
from PyQt4.QtGui import QApplication
from urllib2 import URLError, HTTPError
import urllib2
import os

class DownloadThread(QThread):

    def __init__(self, id, parent=None):
        QThread.__init__(self,parent)
        self.m_overwriteCondition = QWaitCondition()
        self.m_overwriteMutex = QMutex()
        self.m_fileQueue = []
        self.id = id

    def setDestFolder(self, destFolder):
        """Set the destination folder of the file"""

        self.m_destFolder = destFolder

    def setOverwriteAll(self, overwriteAll):
        """Set if all files will be overwrited"""

        self.m_overwriteAll = overwriteAll

    def enqueueFile(self, url, fileLen):
        """Put a file on the download queue"""

        list = []
        list.append(url)
        list.append(str(fileLen))
        self.m_fileQueue.append(list);

        if not self.isRunning():
            self.start();

    def confirmOverwrite(self, result):
        """Confirm the overwrite question come from the main interface"""

        self.m_overwriteResult = result;
        self.m_overwriteCondition.wakeOne();

    def run(self):

        """Download all enqueded files"""

        destFolder = self.m_destFolder;
        overwriteAll = self.m_overwriteAll;

        while len(self.m_fileQueue) != 0:
            fileData = self.m_fileQueue.pop(0);
            url = fileData[0]
            file_len = float(fileData[1])

            targetFile = QString("");

            targetFile = destFolder.absolutePath() \
                       + QDir.separator() + url.split('/')[-1];

            if QFile.exists(targetFile) and not overwriteAll:
                self.m_overwriteMutex.lock()
                self.m_overwriteResult = 1
                self.emit(SIGNAL("overwriteQuestion(const QString &, int)"),
                          targetFile, self.id)

                self.m_overwriteCondition.wait(self.m_overwriteMutex);
                overwriteResult = self.m_overwriteResult;
                self.m_overwriteMutex.unlock();

                if(overwriteResult == 2):
                    self.m_overwriteAll = True;
                    overwriteAll = True;

                if(overwriteResult == 0) or (overwriteResult == 2):
                    if self.downloadFile(str(url), str(targetFile),
                                         file_len, fileData):
                        #Emit a signal to the main interface to
                        #update the status of a given file
                        self.emit(SIGNAL("fileStatus(const QStringList &, const QString &)"), fileData,
                                  QApplication.translate("DownloadThread", "Downloaded",
                                                         None, QApplication.UnicodeUTF8))
                    else:
                        self.emit(SIGNAL("fileStatus(const QStringList &, const QString &)"), fileData,
                                  QApplication.translate("DownloadThread", "Failed to Download",
                                                         None, QApplication.UnicodeUTF8))

                else:
                    self.emit(SIGNAL("updateDownloadStatus(const QString &, float, int)"),
                              QString(url), 100, file_len)
                    self.emit(SIGNAL("fileStatus(const QStringList &, const QString &)"),
                              fileData,
                              QApplication.translate("DownloadThread", "Skipped",
                                                     None, QApplication.UnicodeUTF8))

            else:
                if self.downloadFile(str(url), str(targetFile),
                                     file_len, fileData):

                    self.emit(SIGNAL("fileStatus(const QStringList &, const QString &)"),fileData,
                              QApplication.translate("DownloadThread", "Downloaded",
                                                     None, QApplication.UnicodeUTF8));
                else:
                    self.emit(SIGNAL("fileStatus(const QStringList &, const QString &)"),fileData,
                              QApplication.translate("DownloadThread", "Failed to Download",
                                                     None, QApplication.UnicodeUTF8))

    def downloadFile(self, url, file_name, length, fileData):

        """
        Download the file represented by the url.
        Sends informations about the download progress to the main interface.
        """

        print "downloadFile"
        if url == "":
            return False

        # Open the url
        try:

            self.emit(SIGNAL("fileStatus(const QStringList &, const QString &)"),fileData,
                                  QApplication.translate("DownloadThread", "Establishing Connection...",
                                  None, QApplication.UnicodeUTF8))

            f = urllib2.urlopen(url)

            print "Downloading to" + file_name

            # Open our local file for writing
            local_file = open(file_name, "wb")

            bytesRead = 0.0
            #Write to our local file
            while True:
                try:
                    bytes = f.read(1024)
                    bytesRead += len(bytes)
                    fraction = float((100 * bytesRead) / length)
                    local_file.write(bytes)
                    self.emit(SIGNAL("updateDownloadStatus(const QString &, float, int)"),
                                QString(url), fraction, len(bytes))

                    if bytes == "":
                        local_file.close()
                        break
                except:
                    print "Error saving file %s" % (file_name)
                    local_file.close()
                    os.remove(file_name)

            f.close()
            local_file.close()

            return True
        #handle errors
        except HTTPError, exception:
            print "HTTP Error:", exception.code , url
            return False
        except URLError, e:
            print "URL Error:", exception.reason , url
            return False
